#include<cstdio>

#include "MeanFilter.h"

Filter::Filter(int size): filterSize(size)
{;}

Filter::~Filter()
{;}

MeanFilter::MeanFilter(int size) :Filter(size)
{;}

MeanFilter::~MeanFilter()
{;}

Image MeanFilter::Filtering(const Image &input)
{
    int h = input.Height();
    int w = input.Width();
    if(h*w==0)
    {
        Image empty;
        return empty;
    }
    Image img(h, w);
    int size = filterSize;
    int sum1 =0, sum2 =0, sum3 =0, sum4 =0;     //像素和
    int num1 =0, num2 =0, num3 =0, num4 =0;     //计数器
    for(int rgb=0; rgb<3; ++rgb)        //RGB偏移
    {   
        //中央非边界区
        for(int i=size/2; i<h-size/2; ++i)
            for(int j=size/2*3+rgb; j<(w-size/2)*3; j+=3)
            {
                sum1 = 0;
                for(int p=-size/2; p<=size/2; ++p)
                    for(int q=-size/2*3; q<=size/2*3; q+=3)
                        sum1 += input.At(i+p, j+q);                     //中央区域
                img.Set(i, j) = sum1/(size*size);
            }
        //上下两边界区
        for(int i=0; i<size/2; ++i)
            for(int j=size/2*3+rgb; j<(w-size/2)*3; j+=3)
            {
                sum1 = sum2 = 0;
                num1 = num2 =0;
                for(int p=-size/2; p<=size/2; ++p)
                {
                    if(i+p<0) continue;
                    for(int q=-size/2*3; q<=size/2*3; q+=3)
                    {
                        sum1 += input.At(i+p, j+q);                     //下边缘
                        ++num1;
                        sum2 += input.At(h-1-(i+p), j+q);               //上边缘
                        ++num2;
                    }
                }
                img.Set(i, j) = sum1/num1;
                img.Set(h-1-i, j) = sum2/num2;
            }
        //左右两边界区
        for(int i=size/2; i<h-size/2; ++i)
            for(int j=rgb; j<size/2*3; j+=3)
            {
                sum1 = sum2 = 0;
                num1 = num2 =0;
                for(int q=-size/2*3; q<=size/2*3; q+=3)
                {
                    if(j+q<0) continue;
                    for(int p=-size/2; p<=size/2; ++p)
                    {
                        sum1 += input.At(i+p, j+q);                     //左边缘
                        ++num1;
                        sum2 += input.At(i+p, (w-1-j/3)*3+rgb-q);       //右边缘
                        ++num2;
                    }
                }
                img.Set(i, j) = sum1/num1;
                img.Set(i, (w-1-j/3)*3+rgb) = sum2/num2;
            }
        //四角边界区
        for(int i=0; i<size/2; ++i)
            for(int j=rgb; j<size/2*3; j+=3)
            {
                sum1 = sum2 = 0;
                num1 = num2 =0;
                for(int p=-size/2; p<=size/2; ++p)
                {
                    if(i+p<0) continue;
                    for(int q=-size/2*3; q<=size/2*3; q+=3)
                    {
                        if(j+q<0) continue;
                        sum1 += input.At(i+p, j+q);                     //左下角
                        ++num1;
                        sum2 += input.At(h-1-(i+p), j+q);               //左上角
                        ++num2;
                        sum3 += input.At(i+p, (w-1-j/3)*3+rgb-q);       //右下角
                        ++num3;
                        sum4 += input.At(h-1-(i+p), (w-1-j/3)*3+rgb-q); //右上角
                        ++num4;
                    }
                }
                img.Set(i, j) = sum1/num1;
                img.Set(h-1-i, j) = sum2/num2;
                img.Set(i, (w-1-j/3)*3+rgb) = sum3/num3;
                img.Set(h-1-i, (w-1-j/3)*3+rgb) = sum4/num4;
            }
    }
    return img;
}
